//package com.jfcom.directorymonitor.service.impl;
//
//import com.jfcom.directorymonitor.domain.FileEvent;
//import com.jfcom.directorymonitor.service.FileEventProcessor;
//import jakarta.annotation.PreDestroy;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.dao.DataAccessException;
//import org.springframework.retry.annotation.Backoff;
//import org.springframework.retry.annotation.Retryable;
//import org.springframework.scheduling.annotation.Async;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//import org.springframework.transaction.support.TransactionTemplate;
//import org.springframework.util.StringUtils;
//
//import java.nio.file.Path;
//import java.nio.file.Paths;
//import java.time.LocalDateTime;
//import java.util.Queue;
//import java.util.concurrent.ConcurrentLinkedQueue;
//import java.util.concurrent.ExecutorService;
//import java.util.concurrent.Executors;
//import java.util.concurrent.TimeUnit;
//import java.util.concurrent.atomic.AtomicInteger;
//
//@Service
//@Slf4j
//public class FileEventService {
//
//    private final FileEventRepository fileEventRepository;
//    private final FileEventProcessor fileEventProcessor;
//    private final TransactionTemplate transactionTemplate;
//
//    // 批量处理队列
//    private final Queue<FileEvent> eventBatchQueue = new ConcurrentLinkedQueue<>();
//    private final AtomicInteger batchCounter = new AtomicInteger(0);
//    private final ExecutorService batchExecutor = Executors.newSingleThreadExecutor();
//
//    // 配置参数 (可从配置中心动态获取)
//    private int batchSize = 50; // 批量提交大小
//    private long batchIntervalMs = 500; // 批量提交间隔(ms)
//    private int maxRetryAttempts = 3; // 最大重试次数
//
//    public FileEventService(FileEventRepository fileEventRepository,
//                            FileEventProcessor fileEventProcessor,
//                            TransactionTemplate transactionTemplate) {
//        this.fileEventRepository = fileEventRepository;
//        this.fileEventProcessor = fileEventProcessor;
//        this.transactionTemplate = transactionTemplate;
//
//        // 启动批量处理线程
//        startBatchProcessing();
//    }
//
//    /**
//     * 处理文件事件 (主入口)
//     */
//    @Async("fileEventExecutor")
//    public void processEvent(String eventType, String filePath) {
//        // 1. 验证和预处理
//        if (!isValidEvent(eventType, filePath)) {
//            return;
//        }
//
//        // 2. 创建事件对象
//        FileEvent event = createEvent(eventType, filePath);
//
//        // 3. 添加到批量队列
//        eventBatchQueue.offer(event);
//
//        // 4. 检查批量提交条件
//        if (batchCounter.incrementAndGet() >= batchSize) {
//            flushBatch();
//        }
//    }
//
//    /**
//     * 处理重命名事件
//     */
//    @Async("fileEventExecutor")
//    public void processRenameEvent(String oldPath, String newPath) {
//        // 1. 验证路径
//        if (!isValidPath(oldPath) || !isValidPath(newPath)) {
//            return;
//        }
//
//        // 2. 创建事件对象
//        FileEvent event = new FileEvent();
//        event.setEventType("RENAME");
//        event.setFilePath(newPath);
//        event.setOldFilePath(oldPath);
//        event.setEventTime(LocalDateTime.now());
//
//        // 3. 添加到批量队列
//        eventBatchQueue.offer(event);
//
//        // 4. 检查批量提交条件
//        if (batchCounter.incrementAndGet() >= batchSize) {
//            flushBatch();
//        }
//    }
//
//    /**
//     * 事件有效性检查
//     */
//    private boolean isValidEvent(String eventType, String filePath) {
//        // 1. 空值检查
//        if (!StringUtils.hasText(eventType) || !StringUtils.hasText(filePath)) {
//            return false;
//        }
//
//        // 2. 路径有效性检查
//        if (!isValidPath(filePath)) {
//            return false;
//        }
//
//        // 3. 忽略系统文件/临时文件
//        Path path = Paths.get(filePath);
//        String fileName = path.getFileName().toString();
//
//        // 忽略隐藏文件、临时文件、系统文件
//        if (fileName.startsWith(".") ||
//                fileName.endsWith("~") ||
//                fileName.endsWith(".tmp") ||
//                fileName.endsWith(".swp")) {
//            return false;
//        }
//
//        // 4. 忽略特定目录
//        if (filePath.contains("/.git/") ||
//                filePath.contains("/target/") ||
//                filePath.contains("/node_modules/")) {
//            return false;
//        }
//
//        return true;
//    }
//
//    /**
//     * 路径有效性检查
//     */
//    private boolean isValidPath(String filePath) {
//        try {
//            Path path = Paths.get(filePath);
//            // 检查路径是否在监控目录内
//            return path.startsWith(Paths.get("/home/gitlab"));
//        } catch (Exception e) {
//            return false;
//        }
//    }
//
//    /**
//     * 创建事件对象
//     */
//    private FileEvent createEvent(String eventType, String filePath) {
//        FileEvent event = new FileEvent();
//        event.setEventType(eventType);
//        event.setFilePath(filePath);
//        event.setEventTime(LocalDateTime.now());
//        return event;
//    }
//
//    /**
//     * 启动批量处理线程
//     */
//    private void startBatchProcessing() {
//        batchExecutor.execute(() -> {
//            while (!Thread.currentThread().isInterrupted()) {
//                try {
//                    // 定时或定量触发批量提交
//                    if (!eventBatchQueue.isEmpty()) {
//                        if (batchCounter.get() >= batchSize ||
//                                System.currentTimeMillis() % batchIntervalMs == 0) {
//                            flushBatch();
//                        }
//                    }
//                    TimeUnit.MILLISECONDS.sleep(100);
//                } catch (InterruptedException e) {
//                    Thread.currentThread().interrupt();
//                    // 中断前提交剩余事件
//                    flushBatch();
//                } catch (Exception e) {
//                    log.error("批量处理线程异常", e);
//                }
//            }
//        });
//    }
//
//    /**
//     * 批量提交事件到数据库
//     */
//    private void flushBatch() {
//        if (eventBatchQueue.isEmpty()) {
//            batchCounter.set(0);
//            return;
//        }
//
//        // 创建批量副本
//        Queue<FileEvent> batchToProcess = new ConcurrentLinkedQueue<>();
//        while (!eventBatchQueue.isEmpty()) {
//            batchToProcess.add(eventBatchQueue.poll());
//        }
//
//        // 重置计数器
//        batchCounter.set(0);
//
//        // 在事务中处理批量
//        transactionTemplate.execute(status -> {
//            try {
//                // 1. 保存到数据库
//                saveEventsBatch(batchToProcess);
//
//                // 2. 触发后续处理
//                processEventsAsync(batchToProcess);
//
//                return true;
//            } catch (Exception e) {
//                status.setRollbackOnly();
//                handleBatchError(batchToProcess, e);
//                return false;
//            }
//        });
//    }
//
//    /**
//     * 保存事件到数据库 (带重试机制)
//     */
//    @Retryable(value = DataAccessException.class,
//            maxAttempts = 3,
//            backoff = @Backoff(delay = 100, multiplier = 2))
//    private void saveEventsBatch(Queue<FileEvent> events) {
//        // 批量插入 (使用JPA的saveAll)
//        fileEventRepository.saveAll(events);
//    }
//
//    /**
//     * 异步处理事件业务逻辑
//     */
//    @Async("fileEventExecutor")
//    protected void processEventsAsync(Queue<FileEvent> events) {
//        for (FileEvent event : events) {
//            try {
//                // 根据事件类型处理
//                switch (event.getEventType()) {
//                    case "CREATE":
//                        fileEventProcessor.handleFileCreate(event);
//                        break;
//                    case "MODIFY":
//                        fileEventProcessor.handleFileModify(event);
//                        break;
//                    case "DELETE":
//                        fileEventProcessor.handleFileDelete(event);
//                        break;
//                    case "RENAME":
//                        fileEventProcessor.handleFileRename(event);
//                        break;
//                    default:
//                        log.warn("未知事件类型: {}", event.getEventType());
//                }
//            } catch (Exception e) {
//                log.error("处理文件事件失败: {} - {}", event.getEventType(), event.getFilePath(), e);
//                // 标记事件为失败状态
//                markEventAsFailed(event, e.getMessage());
//            }
//        }
//    }
//
//    /**
//     * 批量错误处理
//     */
//    private void handleBatchError(Queue<FileEvent> failedBatch, Exception e) {
//        log.error("批量处理失败, 事件数量: {}", failedBatch.size(), e);
//
//        // 重试单个事件
//        for (FileEvent event : failedBatch) {
//            retrySingleEvent(event, maxRetryAttempts);
//        }
//    }
//
//    /**
//     * 单事件重试机制
//     */
//    private void retrySingleEvent(FileEvent event, int remainingAttempts) {
//        if (remainingAttempts <= 0) {
//            log.error("事件处理达到最大重试次数: {} - {}", event.getEventType(), event.getFilePath());
//            markEventAsFailed(event, "MAX_RETRY_EXCEEDED");
//            return;
//        }
//
//        try {
//            // 延迟后重试
//            TimeUnit.MILLISECONDS.sleep(100 * (maxRetryAttempts - remainingAttempts + 1));
//
//            // 在事务中重试
//            transactionTemplate.execute(status -> {
//                try {
//                    fileEventRepository.save(event);
//                    processEventAsync(event);
//                    return true;
//                } catch (Exception ex) {
//                    status.setRollbackOnly();
//                    retrySingleEvent(event, remainingAttempts - 1);
//                    return false;
//                }
//            });
//        } catch (InterruptedException ie) {
//            Thread.currentThread().interrupt();
//        }
//    }
//
//    /**
//     * 标记事件失败状态
//     */
//    private void markEventAsFailed(FileEvent event, String errorMessage) {
//        try {
//            event.setStatus(FileEvent.FileEventStatus.FAILED);
//            event.setErrorMessage(errorMessage.substring(0, Math.min(255, errorMessage.length())));
//            fileEventRepository.save(event);
//        } catch (Exception e) {
//            log.error("标记事件状态失败: {}", event.getId(), e);
//        }
//    }
//
//    /**
//     * 关闭时清理资源
//     */
//    @PreDestroy
//    public void shutdown() {
//        // 1. 提交剩余事件
//        flushBatch();
//
//        // 2. 关闭线程池
//        batchExecutor.shutdown();
//        try {
//            if (!batchExecutor.awaitTermination(10, TimeUnit.SECONDS)) {
//                batchExecutor.shutdownNow();
//            }
//        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
//        }
//    }
//}